package xuxu.autotest.element;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

import xuxu.autotest.TestException;
import xuxu.autotest.utils.ShellUtils;

public class Position {
    private Pattern pattern = Pattern.compile("([0-9]+)");
    private String tempFile = System.getProperty("java.io.tmpdir");
    // temp路径显示为：/data/data/your_package_name/cache/dumpfile
    private String temp = new File(tempFile + "/dumpfile").getAbsolutePath();
    private Map<Integer, String> attrib = null;
    private ArrayList<HashMap> attribs = null;
    private InputStream xml = null;
    private List<UiDump> dumps = null;

    public Position() {
        File dumpFile = new File(temp);
        if (!dumpFile.exists()) {
            dumpFile.mkdir();
        }
    }

    public static void main(String[] args) {
//        new Position().uidump();
        System.out.println(new Position().findElementByText("XTest").toString());;
        
    }
    private void uidump() {
//        Process ps = null;
//        DataOutputStream os;
//        try {
//            // 被root后的真机执行
//            ps = Runtime.getRuntime().exec("su"); // 切换到root用户后，后面生成的文件所有者和所属组均为root
//            os = new DataOutputStream(ps.getOutputStream());
//            os.writeBytes("uiautomator dump /data/local/tmp/uidump.xml" + "\n");
//            os.writeBytes("mv /data/local/tmp/uidump.xml " + temp + "\n"); // 做好用mv，因为有些真机内没有cp命令
//            os.writeBytes("chmod 777 " + temp + "/uidump.xml" + "\n");
//            os.writeBytes("exit\n");
//            os.flush();
//            ps.waitFor();
//
//        } catch (IOException e) {// 模拟器内一般没有su执行文件，进入IOException块
//            if (!(ShellUtils.getShellOut(ShellUtils.shell("uiautomator dump /data/local/tmp/uidump.xml")).equals(""))) {
//                ShellUtils.shell("mv /data/local/tmp/uidump.xml " + temp);
//            }
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

//        File file = new File(temp + "/uidump.xml").getAbsoluteFile();
        File file = new File("D:\\window_dump.xml").getAbsoluteFile();
        System.out.println("uidump的路径为：" + temp + "/uidump.xml");
        try {
            xml = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        dumps = new UiDumpService().getDumps(xml);
        System.out.println("uidumps:" + dumps.toString());

    }

    public Element findElementByText(String text) {
        return this.findElement(ElementAttribs.TEXT, text);
    }

    public ArrayList<Element> findElementsByText(String text) {
        return this.findElements(ElementAttribs.TEXT, text);
    }

    public Element findElementById(String resourceId) {
        return this.findElement(ElementAttribs.RESOURCE_ID, resourceId);
    }

    public ArrayList<Element> findElementsById(String resourceId) {
        return this.findElements(ElementAttribs.RESOURCE_ID, resourceId);
    }

    public Element findElementByClass(String className) {
        return this.findElement(ElementAttribs.CLASS, className);
    }

    public ArrayList<Element> findElementsByClass(String className) {
        return this.findElements(ElementAttribs.CLASS, className);
    }

    public Element findElementByChecked(String checked) {
        return this.findElement(ElementAttribs.CHECKED, checked);
    }

    public ArrayList<Element> findElementsByChecked(String checked) {
        return this.findElements(ElementAttribs.CHECKED, checked);
    }

    public Element findElementByCheckable(String checkable) {
        return this.findElement(ElementAttribs.CHECKABLE, checkable);
    }

    public ArrayList<Element> findElementsByCheckable(String checkable) {
        return this.findElements(ElementAttribs.CHECKABLE, checkable);
    }

    public Element findElementByContentdesc(String contentdesc) {
        return this.findElement(ElementAttribs.CONTENTDESC, contentdesc);
    }

    public ArrayList<Element> findElementsByContentdesc(String contentdesc) {
        return this.findElements(ElementAttribs.CONTENTDESC, contentdesc);
    }

    public Element findElementByClickable(String clickable) {
        return this.findElement(ElementAttribs.CLICKABLE, clickable);
    }

    public ArrayList<Element> findElementsByClickable(String clickable) {
        return this.findElements(ElementAttribs.CLICKABLE, clickable);
    }

    public ArrayList<int[]> getBoundsByText(String text) {
        return this.getBounds(ElementAttribs.TEXT, text);
    }

    public ArrayList<int[]> getBoundsByID(String resourceId) {
        return this.getBounds(ElementAttribs.RESOURCE_ID, resourceId);
    }

    public ArrayList<int[]> getBoundsByClass(String className) {
        return this.getBounds(ElementAttribs.CLASS, className);
    }

    public ArrayList<int[]> getBoundsByChecked(String checked) {
        return this.getBounds(ElementAttribs.CHECKED, checked);
    }

    public ArrayList<int[]> getBoundsByCheckable(String checkable) {
        return this.getBounds(ElementAttribs.CHECKABLE, checkable);
    }

    public ArrayList<int[]> getBoundsByContentdesc(String contentdesc) {
        return this.getBounds(ElementAttribs.CONTENTDESC, contentdesc);
    }

    public ArrayList<int[]> getBoundsByClickable(String clickable) {
        return this.getBounds(ElementAttribs.CLICKABLE, clickable);
    }

    public ArrayList<String> getTextById(String resourceId) {
        return this.getText(ElementAttribs.CLASS, resourceId);
    }

    public ArrayList<String> getTextByClass(String className) {
        return this.getText(ElementAttribs.CLASS, className);
    }

    private Element findElement(int att, String str) {
        uidump();

        CharSequence input = getAttrib(att, str).get(ElementAttribs.BOUNDS);

        if (input == null) {
            throw new TestException("未找到(" + str + ")");
        }

        Matcher mat = pattern.matcher(input);
        ArrayList<Integer> coords = new ArrayList<Integer>();
        while (mat.find()) {
            coords.add(new Integer(mat.group()));
        }

        int startX = coords.get(0);
        int startY = coords.get(1);
        int endX = coords.get(2);
        int endY = coords.get(3);

        int centerCoordsX = (endX - startX) / 2 + startX;
        int centerCoordsY = (endY - startY) / 2 + startY;

        Element element = new Element();

        element.setX(centerCoordsX);
        element.setY(centerCoordsY);

        return element;
    }

    @SuppressWarnings("rawtypes")
    private ArrayList<Element> findElements(int att, String str) {
        uidump();
        ArrayList<Element> elements = new ArrayList<Element>();
        ArrayList<HashMap> attribs = getAttribs(att, str);

        for (HashMap hashMap : attribs) {
            Matcher mat = pattern.matcher((String) hashMap.get(ElementAttribs.BOUNDS));
            ArrayList<Integer> coords = new ArrayList<Integer>();
            while (mat.find()) {
                coords.add(new Integer(mat.group()));
            }

            int startX = coords.get(0);
            int startY = coords.get(1);
            int endX = coords.get(2);
            int endY = coords.get(3);

            int centerCoordsX = (endX - startX) / 2 + startX;
            int centerCoordsY = (endY - startY) / 2 + startY;

            Element element = new Element();

            element.setX(centerCoordsX);
            element.setY(centerCoordsY);

            elements.add(element);
        }

        return elements;
    }

    @SuppressWarnings("rawtypes")
    private ArrayList<int[]> getBounds(int att, String str) {
        uidump();
        ArrayList<int[]> bounds = new ArrayList<int[]>();
        ArrayList<HashMap> attribs = getAttribs(att, str);

        for (HashMap hashMap : attribs) {
            Matcher mat = pattern.matcher((String) hashMap.get(ElementAttribs.BOUNDS));
            ArrayList<Integer> coords = new ArrayList<Integer>();
            while (mat.find()) {
                coords.add(new Integer(mat.group()));
            }

            int[] bound = new int[] { coords.get(0), coords.get(1), coords.get(2), coords.get(3) };

            bounds.add(bound);
        }

        return bounds;
    }

    @SuppressWarnings("rawtypes")
    private ArrayList<String> getText(int att, String str) {
        uidump();
        ArrayList<String> text = new ArrayList<String>();
        ArrayList<HashMap> attribs = getAttribs(att, str);

        for (HashMap hashMap : attribs) {
            text.add((String) hashMap.get(ElementAttribs.TEXT));
        }

        return text;
    }

    private HashMap<Integer, String> getAttrib(int att, String str) {
        attrib = new HashMap<Integer, String>();
        for (UiDump dump : dumps) {
            Boolean flag = false;
            switch (att) {
            case 0:
                flag = str.equals(dump.getText());
                break;
            case 1:
                flag = str.equals(dump.getResourceId());
                break;
            case 2:
                flag = str.equals(dump.getClassName());
                break;
            case 3:
                flag = str.equals(dump.getChecked());
                break;
            case 4:
                flag = str.equals(dump.getCheckable());
                break;
            case 5:
                flag = str.equals(dump.getContentDesc());
                break;
            case 6:
                flag = str.equals(dump.getCheckable());
                break;
            default:
                break;
            }
            if (flag) {
                attrib.put(ElementAttribs.TEXT, dump.getText());
                attrib.put(ElementAttribs.RESOURCE_ID, dump.getResourceId());
                attrib.put(ElementAttribs.CLASS, dump.getClassName());
                attrib.put(ElementAttribs.CHECKED, dump.getChecked());
                attrib.put(ElementAttribs.CHECKABLE, dump.getCheckable());
                attrib.put(ElementAttribs.CONTENTDESC, dump.getContentDesc());
                attrib.put(ElementAttribs.CLICKABLE, dump.getCheckable());
                attrib.put(ElementAttribs.BOUNDS, dump.getBounds());

                break;
            }
        }

        return (HashMap<Integer, String>) attrib;
    }

    @SuppressWarnings("rawtypes")
    private ArrayList<HashMap> getAttribs(int att, String str) {
        HashMap<Integer, String> temp = null;
        attribs = new ArrayList<HashMap>();
        for (UiDump dump : dumps) {
            Boolean flag = false;
            switch (att) {
            case 0:
                flag = str.equals(dump.getText());
                break;
            case 1:
                flag = str.equals(dump.getResourceId());
                break;
            case 2:
                flag = str.equals(dump.getClassName());
                break;
            case 3:
                flag = str.equals(dump.getChecked());
                break;
            case 4:
                flag = str.equals(dump.getCheckable());
                break;
            case 5:
                flag = str.equals(dump.getContentDesc());
                break;
            case 6:
                flag = str.equals(dump.getCheckable());
                break;
            default:
                break;
            }
            if (flag) {
                temp = new HashMap<Integer, String>();
                temp.put(ElementAttribs.TEXT, dump.getText());
                temp.put(ElementAttribs.RESOURCE_ID, dump.getResourceId());
                temp.put(ElementAttribs.CLASS, dump.getClassName());
                temp.put(ElementAttribs.CHECKED, dump.getChecked());
                temp.put(ElementAttribs.CHECKABLE, dump.getCheckable());
                temp.put(ElementAttribs.CONTENTDESC, dump.getContentDesc());
                temp.put(ElementAttribs.CLICKABLE, dump.getCheckable());
                temp.put(ElementAttribs.BOUNDS, dump.getBounds());

                attribs.add(temp);
            }
            temp = null;
        }

        return attribs;
    }

    private void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
